﻿//127. 单词接龙
//字典 wordList 中从单词 beginWord 到 endWord 的 转换序列 
//是一个按下述规格形成的序列 beginWord->s1->s2 -> ...->sk：
//每一对相邻的单词只差一个字母。
//对于 1 <= i <= k 时，每个 si 都在 wordList 中。注意， beginWord 不需要在 wordList 中。
//sk == endWord
//给你两个单词 beginWord 和 endWord 和一个字典 wordList
//返回 从 beginWord 到 endWord 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列，返回 0 。


class Solution {
public:
    //映射关系
    unordered_map<string, int>   wordid;
    //无向图
    vector<vector<int>>   edge;
    //映射id
    int countnum = 0;
    //建立映射关系
    void addWord(string& word)
    {
        //不存在
        if (!wordid.count(word))
        {
            wordid[word] = countnum++;
            edge.emplace_back();
        }
    }
    //建图
    void addEdge(string& word)
    {
        addWord(word);
        int id1 = wordid[word];
        for (char& it : word)
        {
            char tmp = it;
            it = '*';
            addWord(word);
            int id2 = wordid[word];
            edge[id1].push_back(id2);
            edge[id2].push_back(id1);
            it = tmp;
        }
    }

    int ladderLength(string beginWord, string endWord, vector<string>& wordList)
    {
        //建图
        for (auto& e : wordList)
        {
            addEdge(e);
        }
        addEdge(beginWord);
        if (!wordid.count(endWord))
        {
            return 0;
        }
        vector<int> dis(countnum, INT_MAX);
        int beginId = wordid[beginWord], endID = wordid[endWord];
        dis[beginId] = 0;

        queue<int> que;
        que.push(beginId);
        while (!que.empty())
        {
            int x = que.front();
            que.pop();
            if (x == endID)
            {
                return dis[endID] / 2 + 1;
            }
            for (int& it : edge[x])
            {
                if (dis[it] == INT_MAX)
                {
                    dis[it] = dis[x] + 1;
                    que.push(it);
                }
            }
        }
        return 0;
    }
};